/**
 * axios封装
 * 请求拦截、相应拦截、错误统一处理
 */
import axios from 'axios'
import QS from 'qs'
import router from '../router'
import store from '@/store'
import { Toast, Dialog } from 'vant'
import config from 'config/config'
import { tokenManage, visit } from 'utils/Cache'
import { weixinAuthorize } from 'api/thirdoauth'
import { getUa } from 'utils/utils'

axios.defaults.timeout = 60000 //请求超时时间
axios.defaults.baseURL = config.server
axios.defaults.withCredentials = true

// 请求拦截器
axios.interceptors.request.use(
    (options) => {
        return options
    },
    (error) => {
        return Promise.reject(error)
    }
)

// 响应拦截器
axios.interceptors.response.use(
    (response) => {
        if (response.status === 200) {
            //200说明请求成功

            if (process.env.VUE_APP_ISMICRO == 'true') {
                //是微服务版本
                if (response.error) {
                    //说明token失效了
                    Dialog.alert({
                        title: '提示',
                        message: '登录状态已失效，请重新登录!'
                    }).then(() => {
                        //去登陆
                        _method.goLogin()
                    })
                }
            } else {
                if (response.data.status) {
                    if (response.data.status == -110) {
                        _method._bingPhone()
                    } else if (response.data.status == 404) {
                        _method.replaceOffline()
                    }
                }
            }
            return Promise.resolve(response)
        } else {
            Toast({
                message: '网络请求异常, 请检查您的网络设置后刷新重试!',
                duration: 1500,
                forbidClick: true
            })

            return Promise.reject(response)
        }
    },
    // 服务器状态码不是200的情况
    (error) => {
        if (error && error.response && error.response.status) {
            switch (error.response.status) {
                // 401: 未登录
                case 401:
                    Toast({
                        message: '登录状态已失效，请重新登录!',
                        duration: 1000,
                        forbidClick: true
                    })
                    //去登陆
                    _method.goLogin()
                    break
                default:
                    Toast({
                        message: '网络请求异常, 请检查您的网络设置后刷新重试!',
                        duration: 1500,
                        forbidClick: true
                    })
            }
        } else {
            Toast({
                message: '网络请求异常, 请检查您的网络设置后刷新重试!',
                duration: 1500,
                forbidClick: true
            })
        }
        return Promise.reject(error)
    }
)

const request = {
    /**
     * get方法
     * @param url 请求url, 相对url
     * @param params 请求参数
     * @param config 扩展配置
     */
    get(url, params, options) {
        return this.sendRequest(url, 'GET', params, options)
    },

    /**
     * post方法
     * @param url 请求url, 相对url
     * @param params 请求参数
     * @param config 扩展配置
     */
    post(url, params, options) {
        if (!options) {
            params = QS.stringify(params)
        }
        // end
        return this.sendRequest(url, 'POST', params, options)
    },

    /**
     * 发送请求
     * @param {*} url 请求url, 相对url
     * @param {*} method 请求方法
     * @param {*} params 请求参数
     * @param {*} options 扩展配置
     */
    sendRequest(url, method, params, options) {
        //如果需要过网关, 则要加网关前缀
        if (_method.isNeedGetway(url)) {
            if (_method.isOauthRequest(url)) {
                url = config.getway.oauthPrefix + url
            } else {
                url = config.getway.prefix + url
            }
        }

        let defaultOptions = {
            url: url,
            method: method,
            headers: {}
        }

        if (method == 'GET') {
            defaultOptions.params = params
        } else {
            defaultOptions.data = params
        }

        if (options) {
            options = { ...defaultOptions, ...options }
        } else {
            options = defaultOptions
        }
        // 如果需要token
        if (_method.isNeedToken(url)) {
            //获取认证的头
            let authHeaders = tokenManage.generateAuthHeaders()
            // 判断是否有认证头, 如果有则给每个HTTP都加上
            if (authHeaders) {
                options.headers = { ...options.headers, ...authHeaders }
            } else {
                // 说明没有token, 但又需要认证
                if (tokenManage.isNeedAuth(url)) {
                    // 去登陆
                    _method.goLogin()
                    return new Promise((resolve, reject) => { })
                }
            }
        }
        //游客id
        options.headers.visitorId = visit.getCookieId()

        // 判断配置文件中是否存在shopId，如果有，则使用(一般在本地测试环境下才会shopId，方便本地测试))
		// options.headers.shopId = 8207    // 测试专用
		if(config.shopId) options.headers.shopId = config.shopId
        // options.headers.shopId = 2    // 测试专用
		// options.headers.shopId = 3136    // 正式环境
		// options.headers.shopId = 4142    // 正式环境
		// options.headers.shopId = 6    // 测试专用
        // options.headers.shopId = 370    // 测试专用
        // options.headers.shopId = 7593    // 测试专用
        return new Promise((resolve, reject) => {
            axios
                .request(options)
                .then((res) => {
                    resolve(res.data)
                })
                .catch((err) => {
                    reject(err)
                })

        })
    }
}

//私有的方法
const _method = {
    /**
     * 清除本地token和清空vuex中token对象
     * 去往登录页面
     */
    goLogin() {
        //清除token
        tokenManage.clearToken()
        // 暂时不做微信自动登录
        if (getUa().isWeixin && store.state.enableWeixinLogin) {
            weixinAuthorize(router.currentRoute.fullPath)
        } else {
            //跳转登录页面

            router
                .replace({
                    path: '/login',
                    query: {
                        redirect: router.currentRoute.fullPath
                    }
                })
                .catch((err) => {
                })
        }
    },

    _bingPhone() {
        router.replace({
            path: '/bindingPhone',
            query: {
                redirect: router.currentRoute.fullPath
            }
        })
    },

    //打烊了
    replaceOffline() {
        router
            .replace({
                path: '/offline'
            })
            .catch((err) => {
            })
    },

    /**
     * 判断url是否需要带token, 临时的用法, 后续要改造
     * @param {*} url
     */
    isNeedToken(url) {
        //如果被排除
        if (config.excludeURIs && config.excludeURIs.length) {
            for (let i = 0, len = config.excludeURIs.length; i < len; i++) {
                let uri = config.excludeURIs[i]
                if (url.indexOf(uri) > 0) {
                    return false
                }
            }
        }

        return true
    },

    /**
     * 判断url是否需要过网关, 对于微服务版本需要过网关
     * @param {*} url
     */
    isNeedGetway(url) {
        if (!process.env.VUE_APP_ISMICRO == 'true') {
            //如果不是微服务
            return false
        }

        if (!config.getway) {
            //如果没有配置
            return false
        }

        if (!config.getway.need) {
            //如果不需要
            return false
        }

        //如果被排除
        if (config.getway.excludeURIs && config.getway.excludeURIs.length) {
            for (let i = 0, len = config.getway.excludeURIs.length; i < len; i++) {
                let uri = config.getway.excludeURIs[i]
                if (url.indexOf(uri) != -1) {
                    return false
                }
            }
        }

        return true
    },

    /**
     * 是否是认证的请求
     * @param {} url
     */
    isOauthRequest(url) {
        if (url.indexOf('/oauth') === -1) {
            return false
        }

        return true
    }
}

export default request
